#pragma once
#include <functional>
#include <cstdint>

using namespace std;

class epoller;

class channel {
    using event_callback = std::function<void()>;
public:
    channel(epoller *ep, int fd)
        :_epoller(ep), _fd(fd), _events(0), _revents(0) 
    {}

    ~channel() {
        close(_fd);
        _fd = -1;
    }

    int get_fd() const { 
        return _fd; 
    }
    
    //获取想要监控的事件
    uint32_t get_events() const { 
        return _events; 
    }

    //设置实际就绪的事件
    void set_revents(const uint32_t revents) { 
        _revents = revents; 
    }
    
    void set_read_callback(const event_callback &cb) {
        _read_callback = cb; 
    }

    void set_write_callback(const event_callback &cb) { 
        _write_callback = cb; 
    }

    void set_error_callback(const event_callback &cb) { 
        _error_callback = cb; 
    }

    void set_close_callback(const event_callback &cb) { 
        _close_callback = cb; 
    }

    void set_event_callback(const event_callback &cb) { 
        _event_callback = cb; 
    }

    //当前是否监控了可读
    bool readable() const { 
        return (_events & EPOLLIN); 
    } 

    //当前是否监控了可写
    bool writeable() const { 
        return (_events & EPOLLOUT); 
    }

    //启动读事件监控
    void enable_read() { 
        _events |= EPOLLIN; 
        update(); 
    }

    //启动写事件监控
    void enable_write() { 
        _events |= EPOLLOUT; 
        update(); 
    }

    //关闭读事件监控
    void disable_read() { 
        _events &= ~EPOLLIN; 
        update(); 
    }

    //关闭写事件监控
    void disable_write() { 
        _events &= ~EPOLLOUT; 
        update(); 
    }

    //关闭所有事件监控
    void disable_all() { 
        _events = 0; 
        update(); 
    }

    //移除监控
    void remove();

    void update();

    //事件处理，一旦连接触发了事件，就调用这个函数，自己触发了什么事件如何处理自己决定
    void handle_event() const {
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI)) {
            /*不管任何事件，都调用的回调函数*/
            if(_event_callback) _event_callback();
            if (_read_callback) _read_callback();
        }
        /*有可能会释放连接的操作事件，一次只处理一个*/
        if (_revents & EPOLLOUT) {
            if(_event_callback) _event_callback();
            if (_write_callback) _write_callback();
        }
        else if (_revents & EPOLLERR) {
            if (_error_callback) _error_callback();//一旦出错，就会释放连接，因此要放到前边调用任意回调
        }
        else if (_revents & EPOLLHUP) {
            if (_close_callback) _close_callback();
        }
    }

    
private:
    epoller *_epoller; 
    int _fd;
    uint32_t _events;  // 当前需要监控的事件
    uint32_t _revents; // 当前连接触发的事件

    event_callback _read_callback;   //可读事件被触发的回调函数
    event_callback _write_callback;  //可写事件被触发的回调函数
    event_callback _error_callback;  //错误事件被触发的回调函数
    event_callback _close_callback;  //连接断开事件被触发的回调函数
    event_callback _event_callback;  //任意事件被触发的回调函数
};

